from datetime import datetime, timedelta
from typing import Optional, Dict, Any

from fastapi import HTTPException
from jose import jwt, JWTError, ExpiredSignatureError
from pydantic import BaseModel

from server.etc.settings import settings
from utils.encryption import rsa_encryptor


class TokenData(BaseModel):
    username: Optional[str] = None
    scopes: list[str] = []


def create_access_token(
        data: Dict[str, Any],
        expires_delta: Optional[timedelta] = None
) -> str:
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    return jwt.encode(
        to_encode,
        settings.JWT_SECRET_KEY,
        algorithm=settings.JWT_ALGORITHM
    )

def verify_token(token: str):
    try:
        payload = jwt.decode(
            token,
            settings.JWT_SECRET_KEY,
            algorithms=[settings.JWT_ALGORITHM]
        )
        return payload
    except ExpiredSignatureError:
        # Token 已过期
        raise HTTPException(
            status_code=1401,
            detail={"code": 1401, "msg": "Token 已过期"}
        )
    except JWTError:
        # Token 验证失败（签名错误、格式错误等）
        raise HTTPException(
            status_code=1401,
            detail={"code": 1401, "msg": "Token 验证失败"}
        )
    except Exception:
        # 其他未知错误
        raise HTTPException(
            status_code=1500,
            detail={"code": 1500, "msg": "Token 验证错误"}
        )


def decrypt_password(encrypted_password: str) -> str:
    if not settings.RSA_ENCRYPTION_ENABLED:
        return encrypted_password

    decrypted = rsa_encryptor.decrypt(encrypted_password)
    if decrypted is None:
        raise ValueError("Failed to decrypt password")
    return decrypted